﻿/*   
    Copyright (C) 2009 Galaktika Corporation ZAO

    This file is a part of Galaktika.BusinessMonitor
 
    Galaktika.BusinessMonitor is a free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
      
    You should have received a copy of the GNU General Public License
    along with Galaktika.BusinessMonitor.  If not, see <http://www.gnu.org/licenses/>.
  
    If GPL v.3 is not suitable for your products or company,
    Galaktika Corp provides Galaktika.BusinessMonitor under a flexible commercial license
    designed to meet your specific usage and distribution requirements.
    If you have already obtained a commercial license from Galaktika Corp,
    you can use this file under those license terms.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Reflection;
using System.Web;

namespace Galaktika.BI.Silverlight.ClientApp.Web.Runtime
{
    using Galaktika.BI.Extensibility;
    using System.ComponentModel.Design;

    internal class ServerResources
    {
        #region Consts
        private static class Consts
        {
            public const string GLOBAL_NAMESPACE = "Global";
            public const string NAVMANGER_CLASS_NAME = "NavManager";
            public const string INITIALIZE_METHOD_NAME = "Initialize";
            public const string NAVIGATETO_METHOD_NAME = "NavigateTo";
            public const string GOBACK_METHOD_NAME = "GoBack";
            public const string GOFORWARD_METHOD_NAME = "GoForward";
            public const string PUSHSTATE_METHOD_NAME = "PushState";
            public const string POPSTATE_METHOD_NAME = "PopState";

            public const string BINDABLE_OBJECT_CLASS_NAME = "BindableObject";
            public const string EXECUTION_CONTEXT_CLASS_NAME = "ExecutionContext";

            public const string ACTIONS_CLASS_NAME = "Actions";
            public const string ACTION_INVOKE_METHOD_NAME = "Invoke";

            public const string SCRIPTENGINE_CLASS_NAME = "ScriptEngine";
            public const string EXECUTE_METHOD_NAME = "Execute";

            public const string CURRENT_CLASS_NAME = "Current";
            public const string CALLER_FIELD_NAME = "Caller";
            public const string BINDING_CONTEXT_FIELD_NAME = "BindingContext";

            public const string VARMANAGER_CLASS_NAME = "VarManager";
            public const string VARIABLES_CLASS_NAME = "Variables";

            public const string SPLASH_IMAGE = "SplashImage";
        }
        #endregion

        static object SyncRoot = new object();
        static Assembly m_Asm;
        const string SERVER_DLL = "Server, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
        public static Assembly ServerAssembly
        {
            get
            {
                lock (SyncRoot)
                {
                    if (m_Asm == null)
                    {
                        m_Asm = Assembly.Load(SERVER_DLL);
                        /*
                        InitializeCaller();
                        //InitializeInternal(typeof(IFormNavigator), Consts.NAVMANGER_CLASS_NAME);
                        //InitializeInternal(typeof(IScriptEngine), Consts.SCRIPTENGINE_CLASS_NAME);
                        InitializeInternal(
                            "Galaktika.BI.Runtime.Services.IExecutionContext,Galaktika.BI.Runtime",
                            string.Format("{0}.{1}", Consts.GLOBAL_NAMESPACE, Consts.EXECUTION_CONTEXT_CLASS_NAME), 
                            Consts.VARMANAGER_CLASS_NAME);
                         */
                    }
                }
                return m_Asm;
            }
        }

        /*
        private static void InitializeCaller()
        {
            Type currentType = m_Asm.GetType(string.Format("{0}.{1}",
                Consts.GLOBAL_NAMESPACE, Consts.CURRENT_CLASS_NAME));
            if (currentType != null)
            {
                FieldInfo callerField = currentType.GetField(Consts.CALLER_FIELD_NAME, BindingFlags.Public | BindingFlags.Static);
                if (callerField != null)
                {
                    Type bindableObjectType = m_Asm.GetType(string.Format("{0}.{1}",
                        Consts.GLOBAL_NAMESPACE, Consts.BINDABLE_OBJECT_CLASS_NAME));
                    if (bindableObjectType != null)
                    {
                        callerField.SetValue(null, Activator.CreateInstance(bindableObjectType));
                    }
                }
            }
        }

        private static void InitializeInternal(
            string srvTypeName,
            string srvInstanceTypeName, 
            string className)
        {
            Type srvType = Type.GetType(srvTypeName, true);
            Type srvInstanceType = m_Asm.GetType(srvInstanceTypeName, true);
            IServiceContainer srvContainer = (IServiceContainer)AppManager.Services.GetService(typeof(IServiceContainer));
            if (srvContainer != null)
            {
                srvContainer.AddService(srvType, Activator.CreateInstance(srvInstanceType));
                object srv = AppManager.Services.GetService(srvType);
                if (srv != null)
                {
                    Type type = m_Asm.GetType(
                        string.Format("{0}.{1}", Consts.GLOBAL_NAMESPACE, className));
                    if (type != null)
                    {
                        MethodInfo init = type.GetMethod(Consts.INITIALIZE_METHOD_NAME, BindingFlags.Public | BindingFlags.Static);
                        if (init != null)
                        {
                            init.Invoke(null, new object[] { srv });
                        }
                    }
                }
            }
        }
        */

        private static Dictionary<string, string> m_KeyValues = null;
        private static void EnsureGlobalKeyValues()
        {
            if (m_KeyValues == null)
            {
                m_KeyValues = new Dictionary<string, string>();

                GlobalKeyValueAttribute[] attrs =
                    (GlobalKeyValueAttribute[])ServerAssembly.GetCustomAttributes(typeof(GlobalKeyValueAttribute), false);
                foreach (GlobalKeyValueAttribute attr in attrs)
                {
                    m_KeyValues.Add(attr.Key, attr.Value);
                }
            }
        }

        public static string GetGlobalValue(string key)
        {
            EnsureGlobalKeyValues();

            string value;
            m_KeyValues.TryGetValue(key, out value);

            return value;
        }
    }
}
